package network

import (
	"net"
	"sync"
	"time"
	"log"
)

type TcpClient struct {
	mutex     	sync.RWMutex
	conn      	net.Conn
	delay     	time.Duration
	address   	string
	stop      	chan bool
}

func NewTcpClient(address string) *TcpClient {
	return &TcpClient{stop:make(chan bool), address: address}
}

func (client *TcpClient) Start() {

	log.Println("client start listen:", client.address)

	for {
		client.reconnect()
		client.mutex.RLock()

		ReadMessage(client.conn, func(conn net.Conn, message *Message) {
			log.Println("ReadMessage:", message.Code, string(message.Data))
		})

		client.mutex.RUnlock()

		select {
		case <-client.stop:
			return
		default:
		}
	}
}

func (client *TcpClient) reconnect() {
	var delay time.Duration

	client.mutex.Lock()
	defer client.mutex.Unlock()

	for {
		var err error

		if client.conn != nil {
			client.conn.Close()
		}

		if client.conn, err = net.Dial("tcp", client.address); err == nil {
			break
		}

		log.Fatalln("connect server", client.address, "fail.")

		select {
		case <-client.stop:
			return
		case <-time.After(delay):
		}
	}

	log.Println("connect server", client.address, "success.")
}

func (client *TcpClient) Stop() {
	close(client.stop)

	client.mutex.RLock()
	defer client.mutex.RUnlock()

	if client.conn != nil {
		client.conn.Close()
	}
}

func (client *TcpClient) SendMessage(code int, data []byte) {
	client.mutex.RLock()
	defer client.mutex.RUnlock()

	if client.conn != nil {
		SendMessage(client.conn, code, data)
	}
}
